﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ComputerArchitecture.Core;
using ComputerArchitecture.Core.Logging;
using ComputerArchitecture.Numbers;
using ComputerArchitecture.Units.Integers.Unsigned.Interfaces;

namespace ComputerArchitecture.Units.Integers.Unsigned.Implementations
{
    public class UnsignedCompareUnit : LoggingObject, IUnsignedCompareUnit
    {
        #region Constructors

        public UnsignedCompareUnit(ILoggingService loggingService) : base(loggingService)
        {
        }

        #endregion

        #region Methods



        #endregion

        int ICompareUnit.Compare(IBitNumber first, IBitNumber second)
        {
            return this.Compare((IUnsignedBitNumber) first, (IUnsignedBitNumber) second);
        }

        public int Compare(IUnsignedBitNumber first, IUnsignedBitNumber second)
        {
            ArgumentValidator.NullValidate(first, "first");
            ArgumentValidator.NullValidate(second, "second");
            if (first.Size != second.Size)
            {
                throw new IncompatibleSizeException();
            }
            // construct Xi
            Bit[] xBits = new Bit[first.Size];
            Parallel.For(0, first.Size, i =>
                                            {
                                                xBits[i] = (first[i] & second[i]) | (!first[i] & !second[i]);
                                            });
            // equality
            if (xBits.AsParallel().All(b => b.IsSet))
            {
                return 0;
            }
            // inequality
            // a > b
            Bit firstMore = first[0] & !second[0];
            for (int i = 1; i < first.Size; ++i)
            {
                Bit temp = first[i] & !second[i];
                for (int j = 0; j < i; ++j)
                {
                    temp.And(xBits[j]);
                }
                firstMore.Or(temp);
            }
            if (firstMore.IsSet)
            {
                return 1;
            }
            return -1;
        }
    }
}
